<script lang="ts">
  import type { FFmpeg } from "@ffmpeg/ffmpeg";
  import BottomAppBar, { Section } from "@smui-extra/bottom-app-bar";
  import Button, { Label, Icon } from "@smui/button";
  import { min_app_fs } from "@linksaas-minapp/api";
  import type { ConvertFile } from "./lib/types";
  import { CONVERT_STATE } from "./lib/types";
  import CircularProgress from "@smui/circular-progress";
  import Select, { Option } from "@smui/select";

  export let ffmpeg: FFmpeg;

  function initFs() {
    try {
      ffmpeg.FS("mkdir", "./tmp");
    } catch (e) {
      console.log(e);
    }
    const files = ffmpeg.FS("readdir", "./tmp");
    for (const file of files) {
      if (file == "." || file == "..") {
        continue;
      }
      ffmpeg.FS("unlink", `./tmp/${file}`);
    }
  }

  initFs();

  let fileList: ConvertFile[] = [];
  let destType = "jpeg";

  const addFile = async () => {
    let files = await min_app_fs.readFile(
      true,
      "图片文件",
      ["jpg", "jpeg", "png", "bmp", "gif", "webp", "tiff"]
    );
    const tmpList = fileList.slice();
    files.forEach((item) => {
      tmpList.push({
        fileName: item.file_name,
        fileData: item.file_data,
        destFileName: "",
        state: CONVERT_STATE.CONVERT_STATE_PEND,
      });
    });
    fileList = tmpList;
  };

  const runConvert = async () => {
    const tmpList = fileList.slice();
    for (const item of tmpList) {
      if (item.state != CONVERT_STATE.CONVERT_STATE_PEND) {
        continue;
      }
      item.state = CONVERT_STATE.CONVERT_STATE_RUN;
      item.destFileName = `${item.fileName}.${destType}`;
      fileList = tmpList;
      try {
        ffmpeg.FS(
          "writeFile",
          `./tmp/${item.fileName}`,
          item.fileData
        );
        await ffmpeg.run(
          "-i",
          `./tmp/${item.fileName}`,
          `./tmp/${item.fileName}.${destType}`
        );
        item.state = CONVERT_STATE.CONVERT_STATE_DONE;
      } catch (e) {
        item.state = CONVERT_STATE.CONVERT_STATE_ERROR;
        console.log(e);
      }
      fileList = tmpList;
    }
  };

  const download = async (fileName) => {
    const fileData = ffmpeg.FS("readFile", `./tmp/${fileName}`);
    await min_app_fs.writeFile(
      fileName,
      fileData
    );
  };
</script>

<div>
  <div>
    {#each fileList as file}
      <div class="item">
        <div class="item_left">
          {file.fileName}
        </div>
        <div class="item_right">
          {#if file.state == CONVERT_STATE.CONVERT_STATE_PEND}
            <Icon class="material-icons">timer</Icon>
          {:else if file.state == CONVERT_STATE.CONVERT_STATE_RUN}
            <CircularProgress
              style="height: 24px; width: 24px;"
              indeterminate
            />
          {:else if file.state == CONVERT_STATE.CONVERT_STATE_DONE}
            <span style="position:relative;top:-6px;">{file.destFileName}</span>
            <Icon
              class="material-icons"
              style="cursor:pointer;"
              on:click={() => download(file.destFileName)}>download</Icon
            >
          {:else if file.state == CONVERT_STATE.CONVERT_STATE_ERROR}
            <Icon class="material-icons" style="color:red">error</Icon>
          {/if}
        </div>
      </div>
    {/each}
  </div>
  <BottomAppBar variant="fixed">
    <Section>
      <Button style="color:white;border:1px solid white;" on:click={addFile}>
        <Icon class="material-icons">add</Icon>
        <Label>添加更多文件</Label>
      </Button>
    </Section>
    <Section>
      <Select
        variant="filled"
        style="width:120px;margin-right:20px;"
        noLabel={true}
        bind:value={destType}
      >
        {#each ["jpeg", "png", "bmp", "gif", "webp", "tiff"] as destType}
          <Option value={destType}>{destType}</Option>
        {/each}
      </Select>
      <Button
        style="color:white;background-color:red;"
        on:click={() => {
          runConvert();
        }}
      >
        <Icon class="material-icons">loopoutlined</Icon>
        <Label>转换文件</Label>
      </Button>
    </Section>
  </BottomAppBar>
</div>

<style>
  .item {
    position: relative;
    margin: 20px 20px;
    padding-bottom: 10px;
    border-bottom: 1px solid #e4e4e8;
  }
  .item_right {
    position: absolute;
    right: 10px;
    top: 0px;
  }
</style>
